package com.sh.rpc;


import com.sh.rpc.confige.RegistryConfig;
import com.sh.rpc.confige.RpcConfig;
import com.sh.rpc.constant.RpcConstant;
import com.sh.rpc.registry.Registry;
import com.sh.rpc.registry.RegistryFactory;
import com.sh.rpc.utils.ConfigUtils;
import lombok.extern.slf4j.Slf4j;

/**
 * 维护配置对象
 * 双检测单例模式实现
 *
 * 目标对象使用 volatile 关键字修饰
 * 判断方法加锁 synchronized
 *
 */

@Slf4j
public class RpcApplication {

    // 目标对象  volatile 关键字修饰
    // 一、保证变量的可见性  防止修改不同步
    private static volatile RpcConfig rpcConfig;

    /**
     * 初始化框架, 支持传入自定义配置
     */
    public static void init(RpcConfig newRpcConfig){
        rpcConfig = newRpcConfig;
        log.info("rpc 初始化， 配置信息：{}",newRpcConfig.toString());
        // 注册中心初始化
        RegistryConfig registryConfig = rpcConfig.getRegistryConfig();
        //                                                          etcd
        Registry registry = RegistryFactory.getInstance(registryConfig.getRegistry());  // 获取注册中心对象  etcdRegistry
        registry.init(registryConfig);  // 注册中心初始化   这里就是向 存储系统etcd 中保存自己的信息了
        log.info("注册中心初始化完成， config={}", registryConfig);

        // 注册 ShutdownHook 关闭钩子， 当程序退出时， 执行销毁操作
        Runtime.getRuntime().addShutdownHook(new Thread(() ->{
            log.info( registryConfig.getRegistry() + "开始执行销毁操作...");
            registry.destroy();
            log.info("销毁完成!");
        }));
    }


    /**
     * 初始化
     */
    public static void init(){
        RpcConfig newRpcConfig;
        try {
            // 如果 没有写配置文件， loadConfig 加载时候就会报错
            newRpcConfig =  ConfigUtils.loadConfig(RpcConfig.class, RpcConstant.DEFAULT_PREFIX);
        } catch (Exception e) {
            System.out.println("未找到配置文件，使用默认配置！");
            // 配置文件不存在，使用默认配置
            newRpcConfig = new RpcConfig();
        }
        init(newRpcConfig);
    }


    /**
     * 获取配置对象
     * 双检锁
     */
    public static RpcConfig getRpcConfig(){
        if( rpcConfig==null ) {
            synchronized (RpcApplication.class){
                if( rpcConfig==null ) {
                    init();
                }
            }
        }
        return rpcConfig;
    }


}
